package server.db;

import server.Server;
import server.ServerConfiguration;

import com.db4o.Db4o;
import com.db4o.ObjectServer;
import com.db4o.config.Configuration;
import com.db4o.messaging.MessageContext;
import com.db4o.messaging.MessageRecipient;
import common.administration.Benutzer;
import common.itemhandling.Eintrag;
import common.itemhandling.files.Datei;

/**
 * @author db40 Tutorial und Julius Ollesch
 * 
 *         starts a db4o server with the settings from
 *         {@link ServerConfiguration}. <br>
 * <br>
 *         This is a typical setup for a long running server. <br>
 * <br>
 *         The Server may be stopped from a remote location by running
 *         StopServer. The StartServer instance is used as a MessageRecipient
 *         and reacts to receiving an instance of a StopServer object. <br>
 * <br>
 *         Note that all user classes need to be present on the server side and
 *         that all possible Db4o.configure() calls to alter the db4o
 *         configuration need to be executed on the client and on the server.
 */
public class DBServer extends Thread implements ServerConfiguration,
		MessageRecipient {

	/**
	 * setting the value to true denotes that the server should be closed
	 */
	private boolean stop = false;

	private final String name = "DB40 Server: "; //$NON-NLS-1$

	/**
	 * starts a db4o server using the configuration from
	 * {@link ServerConfiguration}.
	 */
	/*
	 * public static void main(String[] arguments) { new
	 * StartDBServer().runServer(); }
	 */

	public DBServer() {
		super();

	}

	/**
	 * closes this server.
	 */
	public void close() {

		synchronized (this) {
			stop = true;
			this.notifyAll();
		}
	}

	/**
	 * messaging callback
	 * 
	 * @see com.db4o.messaging.MessageRecipient#processMessage(MessageContext,
	 *      Object)
	 */
	public void processMessage(MessageContext con, Object message) {
		if (message instanceof StopDBServer) {
			close();
		}

	}

	/**
	 * opens the ObjectServer, and waits forever until close() is called or a
	 * StopServer message is being received.
	 */
	@Override
	public void run() {
		synchronized (this) {
			Configuration config = Db4o.newConfiguration();
			config.updateDepth(Integer.MAX_VALUE);
			config.activationDepth(Integer.MAX_VALUE);
			config.objectClass(Eintrag.class).cascadeOnUpdate(true);
			config.objectClass(Eintrag.class).cascadeOnActivate(true);

			config.objectClass(Datei.class).cascadeOnUpdate(true);
			config.objectClass(Datei.class).cascadeOnActivate(true);

			config.objectClass(Benutzer.class).cascadeOnUpdate(true);
			config.objectClass(Benutzer.class).cascadeOnActivate(true);

			ObjectServer db4oServer = Db4o.openServer(config, FILE, PORT);

			db4oServer.grantAccess(USER, PASS);

			Server.log(name);

			// Using the messaging functionality to redirect all
			// messages to this.processMessage
			db4oServer.ext().configure().clientServer().setMessageRecipient(
					this);

			// to identify the thread in a debugger
			Thread.currentThread().setName(this.getClass().getName());

			// We only need low priority since the db4o server has
			// it's own thread.
			Thread.currentThread().setPriority(Thread.MIN_PRIORITY);

			while (!stop) {
				// wait forever for notify() from close()

				Server.log((name + Messages
						.getString("DBServer.Message.running"))); //$NON-NLS-1$

				try {
					this.wait(60000);
				} catch (InterruptedException e) {
					// TODO Automatisch erstellter Catch-Block
					e.printStackTrace();
				}

			}
			db4oServer.openClient().commit();
			db4oServer.close();
		}
	}

}
